﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;



namespace OnlineMealOrdering.Extends.JQDataTable
{

    public static class DataTablesHelper
    {        
        public static DataTableConfigVm DataTableVm<TController, TResult>(this HtmlHelper html, string id, Expression<Func<TController, DataTablesResult<TResult>>> exp, IEnumerable<ColDef> columns = null)
        {
            if (columns == null || !columns.Any())
            {
                //var propInfos = typeof (TResult).GetProperties().Where(p => p.GetGetMethod() != null).ToList();
                var propInfos = TypeExtensions.GetSortedProperties<TResult>();
                var columnList = new List<ColDef>();
                foreach (var propertyInfo in propInfos)
                {
                    var displayNameAttribute = (DisplayNameAttribute)propertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), false).FirstOrDefault();
                    var displayName = displayNameAttribute == null ? propertyInfo.Name : displayNameAttribute.DisplayName;

                    var sortableAttribute = (DataTablesSortableAttribute)propertyInfo.GetCustomAttributes(typeof(DataTablesSortableAttribute), false).FirstOrDefault();
                    var sortable = sortableAttribute == null ? true : sortableAttribute.Sortable;

                    var visibleAttribute = (DataTablesVisibleAttribute)propertyInfo.GetCustomAttributes(typeof(DataTablesVisibleAttribute), false).FirstOrDefault();
                    var visible = visibleAttribute == null ? true : visibleAttribute.Visible;

                    columnList.Add(new ColDef()
                    {
                        Name = propertyInfo.Name,
                        DisplayName = displayName,
                        Sortable = sortable,
                        Visible = visible,
                        Type = propertyInfo.PropertyType
                    });
                }
                columns = columnList.ToArray();
            }

            var mi = exp.MethodInfo();
            var controllerName = typeof(TController).Name;
            controllerName = controllerName.Substring(0, controllerName.LastIndexOf("Controller"));
            var urlHelper = new UrlHelper(html.ViewContext.RequestContext);
            var ajaxUrl = urlHelper.Action(mi.Name, controllerName);
            return new DataTableConfigVm(id, ajaxUrl, columns);
        }

        public static DataTableConfigVm DataTableVm<TController, TResult>(this HtmlHelper html, string id, Expression<Action<TController>> exp, IEnumerable<ColDef> columns = null)
        {
            if (columns == null || !columns.Any())
            {
                //var propInfos = typeof (TResult).GetProperties().Where(p => p.GetGetMethod() != null).ToList();
                var propInfos = TypeExtensions.GetSortedProperties<TResult>();
                var columnList = new List<ColDef>();
                foreach (var propertyInfo in propInfos)
                {
                    var displayNameAttribute = (DisplayNameAttribute)propertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), false).FirstOrDefault();
                    var displayName = displayNameAttribute == null ? propertyInfo.Name : displayNameAttribute.DisplayName;

                    var sortableAttribute = (DataTablesSortableAttribute)propertyInfo.GetCustomAttributes(typeof(DataTablesSortableAttribute), false).FirstOrDefault();
                    var sortable = sortableAttribute == null ? true : sortableAttribute.Sortable;

                    var visibleAttribute = (DataTablesVisibleAttribute)propertyInfo.GetCustomAttributes(typeof(DataTablesVisibleAttribute), false).FirstOrDefault();
                    var visible = visibleAttribute == null ? true : visibleAttribute.Visible;

                    columnList.Add(new ColDef()
                    {
                        Name = propertyInfo.Name,
                        DisplayName = displayName,
                        Sortable = sortable,
                        Visible = visible,
                        Type = propertyInfo.PropertyType
                    });
                }
                columns = columnList.ToArray();
            }

            var mi = exp.MethodInfo();
            var controllerName = typeof(TController).Name;
            controllerName = controllerName.Substring(0, controllerName.LastIndexOf("Controller"));

            var urlHelper = new UrlHelper(html.ViewContext.RequestContext);
            var ajaxUrl = urlHelper.Action(mi.Name, controllerName);
            return new DataTableConfigVm(id, ajaxUrl, columns);
        }

        public static DataTableConfigVm DataTableVm(this HtmlHelper html, string id, string ajaxUrl, params string[] columns)
        {
            return new DataTableConfigVm(id, ajaxUrl, columns.Select(c => ColDef.Create(c, (string)null, typeof(string))));
        }
    }

    public static class TypeExtensions
    {
        public static IEnumerable<PropertyInfo> GetSortedProperties(this Type t)
        {
            return from pi in t.GetProperties()
                   let da = (DisplayAttribute)pi.GetCustomAttributes(typeof(DisplayAttribute), false).SingleOrDefault()
                   let order = ((da != null && da.GetOrder() != null && da.GetOrder() >= 0) ? da.Order : int.MaxValue)
                   orderby order
                   select pi;
        }

        public static IEnumerable<PropertyInfo> GetSortedProperties<T>()
        {
            return typeof(T).GetSortedProperties();
        }
        public static IEnumerable<PropertyInfo> GetProperties(this Type t)
        {
            return from pi in t.GetProperties()
                   select pi;
        }

        public static IEnumerable<PropertyInfo> GetProperties<T>()
        {
            return typeof(T).GetSortedProperties();
        }
    }
}